<template>
  <cjui-page-panel header="Audio 音频波形">
    <template #intro>
      音频波形的实现效果。
    </template>

    <div class="flex flex-col">
      <canvas ref="canvasRef" class="bg-[#f1f3f4] mb-10px rounded-4px"></canvas>
      <audio ref="audioRef" src="/cjui-admin-vue3/audios/solitude.mp3" controls class="w-full h-30px"></audio>
    </div>
  </cjui-page-panel>
</template>

<script lang="ts" setup>
const canvasRef = ref()
const audioRef = ref()

let isInit = false
let analyser: any
let dataArray: any
function audioOnplay() {
  if (isInit) {
    return
  }

  const audioCtx = new AudioContext() // 创建音频上下文
  const source = audioCtx.createMediaElementSource(audioRef.value) // 创建音频源节点
  analyser = audioCtx.createAnalyser()
  analyser.fftSize = 512
  // 创建数组接收分析器数据
  dataArray = new Uint8Array(analyser.frequencyBinCount)
  source.connect(analyser)
  analyser.connect(audioCtx.destination)

  isInit = true
}

let ctx: any
function initCtx() {
  ctx = canvasRef.value.getContext('2d')
  ctx.fillStyle = '#78c5f7'
}

function draw() {
  if (!canvasRef.value) {
    return
  }

  requestAnimationFrame(draw)

  if (!isInit) {
    return
  }

  // 清空画布
  const { width, height } = canvasRef.value
  ctx.clearRect(0, 0, width, height + 10)

  // 让分析器分析数据
  analyser.getByteFrequencyData(dataArray)
  const len = dataArray.length / 2.5
  const barWidth = width / len / 2
  for (let i = 0; i < len; i++) {
    const data = dataArray[i]
    const barHeight = data / 255 * height
    const x1 = i * barWidth + width / 2
    const x2 = width / 2 - (i + 1) * barWidth
    const y = height - barHeight
    ctx.fillRect(x1, y, barWidth, barHeight)
    ctx.fillRect(x2, y, barWidth, barHeight)
  }
}

function init() {
  audioRef.value.onplay = audioOnplay
  initCtx()
  draw()
}

onMounted(() => {
  init()
})
</script>
